package org.medusa.db.handlersocket;

import org.medusa.core.EventCallback;
import org.medusa.core.EventPump;
import org.medusa.db.AsyncDBConnector;
import org.medusa.log.ILog;

public class AsyncHandlerSocket extends AsyncDBConnector {
	// info
	private EventPump evp;
	private EventPump logic_evp;
	private String name;
	private ILog log;

	private HSConnector conn_r;
	private HSConnector conn_wr;

	private AsyncHandlerSocket self = null;

	private long EV_INSERT;
	private long EV_REMOVE;
	private long EV_MODIFY;
	private long EV_QUERY;
	private long EV_QUERY_ONE;

	private long EV_RESULT_INSERT;
	private long EV_RESULT_MODIFY;
	private long EV_RESULT_QUERY;
	private long EV_RESULT_QUERY_ONE;

	public AsyncHandlerSocket(String name, ILog log, EventPump logic_evp) {
		this.self = this;
		this.evp = new EventPump(name);
		this.name = name;
		this.log = log;
		this.logic_evp = logic_evp;
		this.conn_r = new HSConnector(this.name + "(r)", log, false);
		this.conn_wr = new HSConnector(this.name + "(wr)", log, false);

		this.init_ev();
	}

	public Error Connect(String host_r, int port_r, String passwd_r,
			String host_wr, int port_wr, String passwd_wr) {
		this.conn_r.Connect(host_r, port_r, passwd_r);
		return this.conn_wr.Connect(host_wr, port_wr, passwd_wr);
	}

	@Override
	public boolean IsConnected() {
		return this.conn_r.IsConnected() && this.conn_wr.IsConnected();
	}

	@Override
	public Error Close() {
		this.evp.Stop();
		this.conn_r.Close();
		return this.conn_wr.Close();
	}

	@Override
	public void Insert(String dbName, String tableName, String indexName,
			String[] columns, Object[] vals,
			EventCallback<InsertResult> callback) {
		this.evp.DispatchEvent(this.EV_INSERT, dbName, tableName, indexName,
				columns, vals, callback);
	}

	@Override
	public void Modify(String dbName, String tableName, String indexName,
			String oper, Object[] keys, String[] columns, Object[] newvals,
			int limit, int skip, EventCallback<ModifyResult> callback) {
		this.evp.DispatchEvent(this.EV_MODIFY, dbName, tableName, indexName,
				oper, keys, columns, newvals, limit, skip, callback);
	}

	@Override
	public void Remove(String dbName, String tableName, String indexName,
			String oper, Object[] keys, int limit, int skip,
			EventCallback<ModifyResult> callback) {
		this.evp.DispatchEvent(this.EV_REMOVE, dbName, tableName, indexName,
				oper, keys, limit, skip, callback);
	}

	@Override
	public void Query(String dbName, String tableName, String indexName,
			String oper, Object[] keys, String[] columns, int limit, int skip,
			EventCallback<QueryResult> callback) {

		this.evp.DispatchEvent(this.EV_QUERY, dbName, tableName, indexName,
				oper, keys, columns, limit, skip, callback);
	}

	@Override
	public void QueryOne(String dbName, String tableName, String indexName,
			String oper, Object[] keys, String[] columns, int skip,
			EventCallback<QueryOneResult> callback) {

		this.evp.DispatchEvent(this.EV_QUERY_ONE, dbName, tableName, indexName,
				oper, keys, columns, skip, callback);
	}

	public void init_ev() {
		// 发运行结果给evp，evp处理时拿出参数1函数对象，拿出参数2传给参数1的函数
		// evp是否按照增删改查做4个回调，需要思考
		this.EV_RESULT_INSERT = this.logic_evp
				.AddEventListener(new EventCallback<Object[]>() {
					@Override
					public void execute(Object[] args) {
						@SuppressWarnings("unchecked")
						EventCallback<InsertResult> dbr = (EventCallback<InsertResult>) (args[0]);
						InsertResult result = (InsertResult) args[1];
						dbr.execute(result);
					}

					@Override
					public void removed() {
						// TODO Auto-generated method stub
						
					}

				});

		this.EV_RESULT_MODIFY = this.logic_evp
				.AddEventListener(new EventCallback<Object[]>() {
					@Override
					public void execute(Object[] args) {
						@SuppressWarnings("unchecked")
						EventCallback<ModifyResult> dbr = (EventCallback<ModifyResult>) args[0];
						ModifyResult result = (ModifyResult) args[1];
						dbr.execute(result);
					}

					@Override
					public void removed() {
						// TODO Auto-generated method stub
						
					}

				});

		this.EV_RESULT_QUERY = this.logic_evp
				.AddEventListener(new EventCallback<Object[]>() {
					@Override
					public void execute(Object[] args) {
						@SuppressWarnings("unchecked")
						EventCallback<QueryResult> dbr = ((EventCallback<QueryResult>) args[0]);
						QueryResult result = (QueryResult) args[1];
						dbr.execute(result);
					}

					@Override
					public void removed() {
						// TODO Auto-generated method stub
						
					}

				});

		this.EV_RESULT_QUERY_ONE = this.logic_evp
				.AddEventListener(new EventCallback<Object[]>() {
					@Override
					public void execute(Object[] args) {
						@SuppressWarnings("unchecked")
						EventCallback<QueryOneResult> dbr = (EventCallback<QueryOneResult>) args[0];
						QueryOneResult result = (QueryOneResult) args[1];
						dbr.execute(result);
					}

					@Override
					public void removed() {
						// TODO Auto-generated method stub
						
					}

				});

		this.EV_INSERT = this.evp
				.AddEventListener(new EventCallback<Object[]>() {
					@Override
					public void execute(Object[] args) {
						String dbName = (String) args[0];
						String tableName = (String) args[1];
						String indexName = (String) args[2];
						String[] columns = (String[]) args[3];
						Object[] vals = (Object[]) args[4];
						Object dbr = (Object) args[5];

						InsertResult result = self.callback_insert(dbName,
								tableName, indexName, columns, vals);
						if (dbr != null)
							self.logic_evp.DispatchEvent(self.EV_RESULT_INSERT,
									dbr, result);

					}

					@Override
					public void removed() {
						// TODO Auto-generated method stub
						
					}

				});

		this.EV_REMOVE = this.evp
				.AddEventListener(new EventCallback<Object[]>() {
					@Override
					public void execute(Object[] args) {
						String dbName = (String) args[0];
						String tableName = (String) args[1];
						String indexName = (String) args[2];
						String oper = (String) args[3];
						Object[] keys = (Object[]) args[4];
						int limit = (Integer) args[5];
						int skip = (Integer) args[6];
						Object dbr = args[7];

						ModifyResult result = self.callback_remove(dbName,
								tableName, indexName, oper, keys, limit, skip);
						if (dbr != null)
							self.logic_evp.DispatchEvent(self.EV_RESULT_MODIFY,
									dbr, result);
					}

					@Override
					public void removed() {
						// TODO Auto-generated method stub
						
					}

				});
		this.EV_MODIFY = this.evp
				.AddEventListener(new EventCallback<Object[]>() {
					@Override
					public void execute(Object[] args) {

						String dbName = (String) args[0];
						String tableName = (String) args[1];
						String indexName = (String) args[2];
						String oper = (String) args[3];
						Object[] keys = (Object[]) args[4];
						String[] columns = (String[]) args[5];
						Object[] newvals = (Object[]) args[6];
						int limit = (Integer) args[7];
						int skip = (Integer) args[8];
						Object dbr = args[9];

						ModifyResult result = self.callback_modify(dbName,
								tableName, indexName, oper, keys, columns,
								newvals, limit, skip);
						if (dbr != null)
							self.logic_evp.DispatchEvent(self.EV_RESULT_MODIFY,
									dbr, result);

					}

					@Override
					public void removed() {
						// TODO Auto-generated method stub
						
					}

				});
		this.EV_QUERY = this.evp
				.AddEventListener(new EventCallback<Object[]>() {
					@Override
					public void execute(Object[] args) {
						String dbName = (String) args[0];
						String tableName = (String) args[1];
						String indexName = (String) args[2];
						String oper = (String) args[3];
						Object[] keys = (Object[]) args[4];
						String[] columns = (String[]) args[5];
						int limit = (Integer) args[6];
						int skip = (Integer) args[7];
						Object dbr = args[8];

						QueryResult result = self.callback_query(dbName,
								tableName, indexName, oper, keys, columns,
								limit, skip);
						if (dbr != null)
							self.logic_evp.DispatchEvent(self.EV_RESULT_QUERY,
									dbr, result);
					}

					@Override
					public void removed() {
						// TODO Auto-generated method stub
						
					}

				});
		this.EV_QUERY_ONE = this.evp
				.AddEventListener(new EventCallback<Object[]>() {
					@Override
					public void execute(Object[] args) {
						String dbName = (String) args[0];
						String tableName = (String) args[1];
						String indexName = (String) args[2];
						String oper = (String) args[3];
						Object[] keys = (Object[]) args[4];
						String[] columns = (String[]) args[5];
						int skip = (Integer) args[6];
						Object dbr = args[7];

						QueryOneResult result = self
								.callback_queryone(dbName, tableName,
										indexName, oper, keys, columns, skip);
						if (dbr != null)
							self.logic_evp.DispatchEvent(
									self.EV_RESULT_QUERY_ONE, dbr, result);
					}

					@Override
					public void removed() {
						// TODO Auto-generated method stub
						
					}

				});
	}

	private InsertResult callback_insert(String dbName, String tableName,
			String indexName, String[] columns, Object[] vals) {
		return this.conn_wr.Insert(dbName, tableName, indexName, columns, vals);
	}

	private ModifyResult callback_remove(String dbName, String tableName,
			String indexName, String oper, Object[] keys, int limit, int skip) {
		return this.conn_wr.Remove(dbName, tableName, indexName, oper, keys,
				limit, skip);
	}

	private ModifyResult callback_modify(String dbName, String tableName,
			String indexName, String oper, Object[] keys, String[] columns,
			Object[] newvals, int limit, int skip) {
		return this.conn_wr.Modify(dbName, tableName, indexName, oper, keys,
				columns, newvals, limit, skip);
	}

	private QueryResult callback_query(String dbName, String tableName,
			String indexName, String oper, Object[] keys, String[] columns,
			int limit, int skip) {
		return this.conn_r.Query(dbName, tableName, indexName, oper, keys,
				columns, limit, skip);
	}

	private QueryOneResult callback_queryone(String dbName, String tableName,
			String indexName, String oper, Object[] keys, String[] columns,
			int skip) {
		return this.conn_r.QueryOne(dbName, tableName, indexName, oper, keys,
				columns, skip);
	}

	public void Error(Object... args) {
		if (this.log != null)
			this.log.Error(this.name, args);
	}

	public void Warning(Object... args) {
		if (this.log != null)
			this.log.Warning(this.name, args);
	}

	public void Success(Object... args) {
		if (this.log != null)
			this.log.Success(this.name, args);
	}

	public void Debug(Object... args) {
		if (this.log != null)
			this.log.Debug(this.name, args);
	}

	public void Stack(Object... args) {
		if (this.log != null)
			this.log.Stack(this.name, args);
	}

	public void Temp(Object... args) {
		if (this.log != null)
			this.log.Temp(this.name, args);
	}

}
